#include <linux/types.h>
#include <stdbool.h>
#include <stdio.h>
#include <stm32f1xx.h>

#include "bookpack.h"
#include "fonts.h"
#include "graphic.h"
#include "linux/jiffies.h"
#include "log.h"
#include "memory.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_gpio.h"
#include "stm32f1xx_hal_tim.h"
#include "timer.h"
#include "types.h"
#include "utils.h"

/****************************************************************************
 * Function Name  : SRAM_WriteBuffer
 * Description    : 向SRAM里面写入一定长度的数据
 * Input          : writeBuf：写入缓存
 *                * writeAddr：写入起始地址
 *                * length：写入数据长度
 * Output         : None
 * Return         : None
 ****************************************************************************/

#define Bank1_SRAM3_ADDR ((uint32_t)(0x68000000))
void SRAM_WriteBuffer(uint16_t *writeBuf, uint32_t writeAddr, uint32_t length) {
    while (length--) /*!< while there is data to write */
    {
        /*!< Transfer data to the memory */
        *(uint16_t *)(Bank1_SRAM3_ADDR + writeAddr) = *writeBuf++;

        /*  十六位长度的是地址+2 */
        writeAddr += 2;
    }
}

/****************************************************************************
 * Function Name  : SRAM_ReadBuffer
 * Description    : 读取SRAM数据
 * Input          : readBuff：读取缓存
 *                * readAddr：读取起始地址
 *                * length：读取数据长度
 * Output         : None
 * Return         : None
 ****************************************************************************/

void SRAM_ReadBuffer(uint16_t *readBuff, uint32_t readAddr, uint32_t length) {
    while (length--) /*!< while there is data to read */
    {
        /*!< Read a half-word from the memory */
        *readBuff++ = *(__IO uint16_t *)(Bank1_SRAM3_ADDR + readAddr);

        /*  十六位长度的是地址+2 */
        readAddr += 2;
    }
}

void SRAM_Test(void) {
    uint8_t showData[5] = {0, 0, 0, 0, 0};
    uint16_t writeData = 0xf0f0, readData, cap = 0;
    uint32_t addr;

    put_font8_str(TFT_XMAX, 0, 84, COL8_FF0000, COL8_000000, "SRAM     KB");
    /* 每隔一个1KB写入一个数据，然后读取数据，如果不相同，那么就满了 */
    addr = 1024;  // 从1KB位置开始算起
    while (1) {
        SRAM_WriteBuffer(&writeData, addr, 1);  // 写入
        SRAM_ReadBuffer(&readData, addr, 1);    // 读取

        /* 查看读取到的数据是否跟写入数据一样 */
        if (readData == writeData) {
            cap++;
            addr += 1024;
            readData = 0;
            if (addr > 1024 * 3099)  // SRAM容量最大为1MB
            {
                break;
            }
        } else {
            break;
        }
    }

    /* 显示读取到的容量 */
    showData[0] = (cap % 10000 / 1000) + '0';
    showData[1] = (cap % 1000 / 100) + '0';
    showData[2] = (cap % 100 / 10) + '0';
    showData[3] = (cap % 10) + '0';

    put_font8_str(TFT_XMAX, 144, 84, COL8_FF0000, COL8_000000, showData);
}

void memory_show() {
    u32 start = 0x68000000;
    u32 end = 0x6810ffff;
    int i = 0;
    u32 t_end = memtest(start, end);
    LOG_INFO("start 0x%x, end 0x%x", start, t_end);
    char s[255] = {0};
    sprintf(s, "0x%x ~ 0x%x", start, t_end);
    put_font8_str(TFT_XMAX, 0, i * 8, COL8_FFFF00, COL8_CCCCCC, s);
}

extern TIM_HandleTypeDef htim3;

void HariMain(void) {
    LOG_INFO("hello, main");
    /* FIFO32Type timer_fifo; */
    /* fifo32_init(&timer_fifo, NULL); */
    /* struct TIMER timer1; */
    /* timer_init(&timer1, &timer_fifo, 1); */
    /* timer_settime(&timer1, jiffies + msecs_to_jiffies(1000)); */
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
    TFT_Init();                       // TFT彩屏初始化
    init_screen(TFT_XMAX, TFT_YMAX);  // 清屏
    /* memory_show(); */
    while (true) {
        LOG_INFO("one period");
        /* HAL_Delay(300); */
        uint16_t pmw_val = 0;
        while (pmw_val < 400) {
            pmw_val++;
            __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pmw_val);
            HAL_Delay(1);
        }
        while (pmw_val) {
            pmw_val--;
            __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, pmw_val);
            HAL_Delay(1);
        }

        /* if (fifo32_is_empty(&timer_fifo)) { */
            /* io_hlt(); */
            /* continue; */
        /* } */

        /* int data; */
        /* fifo32_get(&timer_fifo, &data); */
        /* LOG_INFO("get fifo %d", data); */
        /* if (data == 1) { */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET); */
            /* timer_init(&timer1, &timer_fifo, 0); */
        /* } else { */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET); */
            /* HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); */
            /* timer_init(&timer1, &timer_fifo, 1); */
        /* } */
        /* timer_settime(&timer1, jiffies + msecs_to_jiffies(1000)); */
    }
}
